package com.bozhong.config.parser;

import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;

/**
 * @author fupan
 */
public abstract class AbstractNacosDataParser {
	protected static final String DOT = ".";
	protected static final String VALUE = "value";
	protected static final String EMPTY_STRING = "";
	private final String extension;
	private AbstractNacosDataParser nextParser;

	protected AbstractNacosDataParser(String extension) {
		if (StringUtils.isEmpty(extension)) {
			throw new IllegalArgumentException("extension cannot be empty");
		} else {
			this.extension = extension.toLowerCase();
		}
	}

	public final boolean checkFileExtension(String extension) {
		if (this.isLegal(extension.toLowerCase())) {
			return true;
		} else {
			return this.nextParser != null && this.nextParser.checkFileExtension(extension);
		}
	}

	public final Map<String, Object> parseNacosData(String data, String extension) throws IOException {
		if (extension != null && extension.length() >= 1) {
			if (this.isLegal(extension.toLowerCase())) {
				return this.doParse(data);
			} else if (this.nextParser == null) {
				throw new IllegalStateException(getTips(extension));
			} else {
				return this.nextParser.parseNacosData(data, extension);
			}
		} else {
			throw new IllegalStateException("The file extension cannot be empty");
		}
	}

	protected abstract Map<String, Object> doParse(String data) throws IOException;

	protected AbstractNacosDataParser setNextParser(AbstractNacosDataParser nextParser) {
		this.nextParser = nextParser;
		return this;
	}

	public AbstractNacosDataParser addNextParser(AbstractNacosDataParser nextParser) {
		if (this.nextParser == null) {
			this.nextParser = nextParser;
		} else {
			this.nextParser.addNextParser(nextParser);
		}

		return this;
	}

	protected boolean isLegal(String extension) {
		return this.extension.equalsIgnoreCase(extension) || this.extension.contains(extension);
	}

	protected void flattenedMap(Map<String, Object> result, Map<String, Object> dataMap, String parentKey) {
		Set<Map.Entry<String, Object>> entries = dataMap.entrySet();
		Iterator iterator = entries.iterator();

		while(true) {
			while(iterator.hasNext()) {
				Map.Entry entry = (Map.Entry)iterator.next();
				String key = (String)entry.getKey();
				Object value = entry.getValue();
				String fullKey = StringUtils.isEmpty(parentKey) ? key : (key.startsWith("[") ? parentKey.concat(key) : parentKey.concat(".").concat(key));
				if (value instanceof Map) {
					Map<String, Object> map = (Map)value;
					this.flattenedMap(result, map, fullKey);
				} else if (value instanceof Collection) {
					int count = 0;
					Collection<Object> collection = (Collection)value;
					Iterator var12 = collection.iterator();

					while(var12.hasNext()) {
						Object object = var12.next();
						this.flattenedMap(result, Collections.singletonMap("[" + count++ + "]", object), fullKey);
					}
				} else {
					result.put(fullKey, value);
				}
			}

			return;
		}
	}

	protected Map<String, Object> reloadMap(Map<String, Object> map) {
		if (map != null && !map.isEmpty()) {
			Map<String, Object> result = new LinkedHashMap<>(map);
			Iterator var3 = map.entrySet().iterator();

			while(var3.hasNext()) {
				Map.Entry entry = (Map.Entry)var3.next();
				String key = (String)entry.getKey();
				if (key.contains(".")) {
					int idx = key.lastIndexOf(".");
					String suffix = key.substring(idx + 1);
					if ("value".equalsIgnoreCase(suffix)) {
						result.put(key.substring(0, idx), entry.getValue());
					}
				}
			}

			return result;
		} else {
			return null;
		}
	}

	public static String getTips(String fileName) {
		return String.format("[%s] must contains file extension with properties|yaml|yml|xml|json", fileName);
	}
}
